package com.emip.util.report.impl;

import java.math.BigDecimal;
import java.text.DecimalFormat;

import org.springframework.stereotype.Component;

import com.emip.bean.Store;
import com.emip.config.SysParams;
import com.emip.util.report.Comput;

@Component
public class AverageComput extends Comput {

	BigDecimal sum; 
	DecimalFormat df;
	BigDecimal pH;
	BigDecimal ten;
	boolean isPh;
	boolean isH;
	
	public AverageComput() {
		sum = new BigDecimal(0);
		df = new DecimalFormat("#.##");
		pH = new BigDecimal(7);
		ten = new BigDecimal(10);
	}
	
	@Override
	public void appendData(Store store) {
		//Only valid value using the PH Algorithm
		if (this.flag == null && store.getItemID().equals(SysParams.PH)) {
			isPh = true;
			if (count == 1) {
				sum = new BigDecimal(store.getValue());
			} else {
				sum = computPH(new BigDecimal(store.getValue())).setScale(2, BigDecimal.ROUND_FLOOR);
			}
			if (sum.compareTo(pH) <= 0) isH = true;
			else isH = false;
		} else {
			sum = sum.add(new BigDecimal(store.getValue()));
		}
	}
	
	private BigDecimal computPH(BigDecimal ph) {
		boolean isOH = false;
		if (ph.compareTo(pH) > 0) {
			isOH = true;
		} 
		ph = getValue(ph, !isOH);
		sum = getValue(sum, isH);
		
		if (isOH && !isH) {
			return computOH(sum, ph);
		} else if (!isOH && isH) {
			return computH(sum, ph);
		} else if (isOH && isH) {
			if (ph.compareTo(sum) > 0) {
				return computOH(sum.negate(), ph);
			} else {
				return computH(sum, ph.negate());
			}
		} else {
			if (ph.compareTo(sum) > 0) {
				return computH(sum.negate(), ph);
			} else {
				return computOH(sum, ph.negate());
			}
		}
	}
	
	private BigDecimal getValue(BigDecimal ph, boolean isH) {
		if (isH) {
			return new BigDecimal(Math.pow(10, -ph.doubleValue()));
		}
		return new BigDecimal(Math.pow(10, ph.doubleValue()-14));
	}
	
	private BigDecimal computH(BigDecimal ph, BigDecimal ph2) {
		ph = ph.add(ph2).divide(new BigDecimal(2));
		return new BigDecimal(-Math.log10(ph.doubleValue()));
	}
	
	private BigDecimal computOH(BigDecimal ph, BigDecimal ph2) {
		ph = ph.add(ph2).divide(new BigDecimal(2));
		return new BigDecimal(14+Math.log10(ph.doubleValue()));
	}
	
	//Arithmetic average 
	@Override
	public String getResult() {
		if (count == 0) return "";
		if (isPh) {
			df = new DecimalFormat("#.##");
			return df.format(sum);
		}
		return df.format(sum.divide(new BigDecimal(count), 3, BigDecimal.ROUND_HALF_DOWN));
	}

	@Override
	public Comput newInstance() {
		return new AverageComput();
	}

	@Override
	public String getLabel() {
		return "平均值";
	}
	

}
